package com.bxl.netty.rpc.register.server;


import com.bxl.netty.rpc.client.common.client.AppInfo;
import com.bxl.netty.rpc.client.common.client.ClientInfo;
import com.bxl.netty.rpc.common.pool.ThreadPoolUtil;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * <>
 *
 * @author baixl
 * @date 2021/2/26
 */
public class ZoneInfos {
    private Map<String, AppInfo> zones = new HashMap<String, AppInfo>();
    private int inteval;
    private TimeUnit timeUnit;
    private RegisterServerContext context;
    private SlidingWindow slidingWindow;


    public Map<String, AppInfo> getZones() {
        return zones;
    }

    private ScheduledExecutorService executorService;

    public ZoneInfos(RegisterServerContext context, int inteval, TimeUnit timeUnit) {
        assert context == null;
        this.context = context;
        this.slidingWindow = this.context.getSlidingWindow();
        this.inteval = inteval;
        this.timeUnit = timeUnit;
        init();
    }

    public void init() {
        ThreadPoolUtil.scheduleAtFixedRate(new LeaseCheckTask(context,this), this.inteval, this.inteval, this.timeUnit);
    }

    public AppInfo getZone(String zoneId) {
        return zones.get(zoneId);
    }

    public void setZones(Map<String, AppInfo> zones) {
        this.zones = zones;
    }

    public void addZone(AppInfo zoneInfo) {
        synchronized (zones) {
            AppInfo existsZoneInfo = zones.get(zoneInfo.getApp());
            if (existsZoneInfo != null) {
                //存在 添加 去重
                List<ClientInfo> clients = existsZoneInfo.getClients();
                //第一次注册也算心跳
                ClientInfo clientInfo = zoneInfo.getClients().get(0);
                slidingWindow.register(clientInfo);
                if (clients.contains(clientInfo)) {
                    return;
                } else {
                    clients.add(clientInfo);
                    System.out.println(11);
                }
            } else {
                zones.put(zoneInfo.getApp(), zoneInfo);
            }
        }
    }

    public static class LeaseCheckTask implements Runnable {
        private RegisterServerContext context;
        private Map<String, AppInfo> zones;
        private List<ClientInfo> newClients;
        private SlidingWindow slidingWindow;
        private ZoneInfos zoneInfos;
        private boolean isFirst = true;

        public LeaseCheckTask(RegisterServerContext context,ZoneInfos zoneInfos) {
            this.context = context;
            this.slidingWindow = context.getSlidingWindow();
            this.zoneInfos = zoneInfos;
        }

        public void run() {
            zones = zoneInfos.getZones();
            List<ClientInfo> registerInfos = null;
            try {
                //注册失效 ，但是恢复心跳的数据应该添加进去
                //可以使用读写锁。现在是 采用容器复制
                //
                synchronized (zones) {
                    if (isFirst) {
                        registerInfos = slidingWindow.sttsAll();
                    }
                    if(!zones.isEmpty()){
                        for (Iterator<Map.Entry<String, AppInfo>> iterator = zones.entrySet().iterator(); iterator.hasNext(); ) {
                            Map.Entry<String, AppInfo> next = iterator.next();
                            AppInfo zoneInfo = next.getValue();
                            List<ClientInfo> clients = zoneInfo.getClients();
                            //避免每次都创建新的list
                            newClients = zoneInfo.getOldClients();
                            newClients.clear();
                            for (ClientInfo client : clients) {
                                if (slidingWindow.stts(client) > 0) {
                                    newClients.add(client);
                                }
                            }
                            zoneInfo.setClients(newClients);

                            if (isFirst && registerInfos != null) {
                                for (ClientInfo registerInfo : registerInfos) {
                                    if (!newClients.contains(registerInfo)) {
                                        newClients.add(registerInfo);
                                    }
                                }
                            }
                            zoneInfo.setOldClients(clients);
                        } 
                    }else if(isFirst && registerInfos != null){
                        for (ClientInfo registerInfo : registerInfos) {
                            if(zones.get(registerInfo.getApp()) == null){
                                zones.put(registerInfo.getApp(),new AppInfo(registerInfo.getApp()));
                            }
                            if(!zones.get(registerInfo.getApp()).getClients().contains(registerInfo)){
                                zones.get(registerInfo.getApp()).addClients(registerInfo);
                            }
                        }
                    }
                   
                    isFirst = false;
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
